package executor;

import java.io.*;
import java.awt.*;
import java.awt.image.*;

/**
 * Classe che rappresenta un immagine (quadrata) come array di pixel.
 * Serve come stadio intermedio da immagine a quad-tree e viceversa,
 * perche' qui posso accedere i colori dell'immagine per posizione.
 * Ogni colore e' rappresentato con un singolo intero: 4 byte tre dei
 * quali sono usati per rappresentare le componenti rossa, verde, blu 
 * su 8 bit ciascuna.
 * @see QuadColor
 */
public class PixelMatrix
{
  /** Larghezza in pixel dell'immagine, che e' quadrata. */
  protected int width;
  /** Versione linearizzata della matrice, come un unico array dove 
   * le righe sono rappresentate una di seguito all'altra. */
  protected int[] pixelArray;

  /** Ritorna la larghezza in pixel della matrice immagine.
   * @return la larghezza in pixel della matrice immagine
   */
  public int getWidth() { return width; }

  /** Costruisce una matrice immagine quadrata di larghezza assegnata,
   * tutti i pixel sono neri (numero zero).
   * @param w   la larghezza con cui creare l'immagine
   */
  public PixelMatrix(int w)
  {
    pixelArray = new int[w*w];
    width = w;
  }
    
  /** Costruisce una matrice immagine quadrata di larghezza assegnata,
   * copiandola da un'immagine data, a partire da un punto d'aggancio
   * su quest'ultima. Viene copiata la parte di immagine da (x0,y0)
   * per un'ampiezza di w per w.
   * @param w   la larghezza con cui creare l'immagine
   * @param im  immagine da cui copiare i colori
   * @param x0  ascissa del punto d'aggancio su im da dove
   *            partire per copiare i colori
   * @param y0  ordinata del punto d'aggancio su im da dove
   *            partire per copiare i colori
   */
  public PixelMatrix(int x0, int y0, int w, Image im)
  {
    pixelArray = new int[w*w];
    width = w;
    PixelGrabber pg = new PixelGrabber(im, x0, y0, w,w,
                                       pixelArray, 0, w);
    try
    {  pg.grabPixels();
    }
    catch (InterruptedException e) {};
  }

  /** Ritorna la posizione nell'array in cui e' memorizzato il colore
   * del pixel di coordinate (x,y) sull'immagine. 
   * @param x     la coordinata x del pixel
   * @param y     la coordinata y del pixel
   * @return      la posizione del pixel nell'array di pixel che
   *              rappresenta la matrice
   */
  protected int position(int x, int y)  {  return (x+width*y);  }

  /** Ritorna il colore di un pixel date le sue coordinate 
   * sull'immagine. 
   * @param x     la coordinata x del pixel
   * @param y     la coordinata y del pixel
   * @return      il colore del pixel rappresentato su un unico intero
   * @see QuadColor
   */
  public int getColor(int x, int y) 
  {  return pixelArray[position(x,y)];  }

  /** Assegna il colore a un pixel, date le sue coordinate 
   * sull'immagine e il colore come oggetto di classe java Color. 
   * @param x     la coordinata x del pixel
   * @param y     la coordinata y del pixel
   * @param col   il colore da assegnare al pixel
   */
  public void setColor(int x, int y, Color col)
  {
    pixelArray[position(x,y)] = QuadColor.makeColor(col);
  }

  /** Assegna il colore a un pixel, date le sue coordinate 
   * sull'immagine e le tre componenti rossa, verde, blu del colore.
   * @param x     la coordinata x del pixel
   * @param y     la coordinata y del pixel
   * @param red   la componente rossa del colore da assegnare al pixel
   * @param green la componente verde del colore da assegnare al pixel
   * @param blue  la componente blu del colore da assegnare al pixel
   */
  public void setColor(int x, int y, int red, int green, int blue)
  {
    pixelArray[position(x,y)] = QuadColor.makeColor(red, green, blue);
  }

  /** Assegna il colore a un pixel, date le sue coordinate 
   * sull'immagine e il colore come un unico intero.
   * @param x     la coordinata x del pixel
   * @param y     la coordinata y del pixel
   * @param rgb   il colore come singolo intero dove tre byte sono
   *              usati per le tre componenti rossa, verde, blu
   * @see QuadColor
   */
  public void setColor(int x, int y, int rgb)
  {  pixelArray[position(x,y)] = rgb;  }

  /** Ritorna la stessa immagine, qui memorizzata come array di pixel,
   * come oggetto della classe java Image.
   * @return   la stessa immagine come oggetto della classe java Image
   */
  public Image thisAsImage()
  {
    ColorModel cm = new DirectColorModel(24, 0xff0000, 0xff00, 0xff, 0x0);
    WritableRaster rast = Raster.createPackedRaster(
        new DataBufferInt(pixelArray, width), 
        width, width, width,
        new int[]{0xff0000,0xff00,0xff},null);
    return new BufferedImage(cm, rast, false, null);
  }
}
